#include "BitStream.h"

namespace miniprojeto {
namespace util {

BitStream::BitStream() {
	this->bitIndice = 0;
	this->byteIndice = 0;
	this->byteArrayLen = -1; /* indica que ainda não foi setado um bitArray */
}

BitStream::BitStream(unsigned char byteArray[], int byteArrayLen) {
	this->bitIndice = 0;
	this->byteIndice = 0;
	this->setByteArray(byteArray, byteArrayLen);
}

BitStream::~BitStream() {
	
}

void BitStream::setByteArray(unsigned char byteArray[], int byteArrayLen) {
	if ((byteArrayLen > 0) && (byteArray != NULL)) {
		this->byteArray = byteArray;
		this->byteArrayLen = byteArrayLen;
	} else {
		BadArgumentException excep ((char*) "BitStream::setByteArray()");
		throw excep;
	}
	
}

void BitStream::setBitIndice(int bitIndice) {
	if ((bitIndice >= 0) && (bitIndice < 8)) {
		this->bitIndice = bitIndice;	
	} else {
	BadArgumentException excep ((char*) "BitStream::setBitIndice()");
		throw excep;	
	}
}

void BitStream::setByteIndice(int byteIndice) {
	if ((byteIndice >=0) && (byteIndice < this->byteArrayLen)) {
		this->byteIndice = byteIndice;
	} else {
		BadArgumentException excep ((char*) "BitStream::setByteIndice()");
		throw excep;	
	}
	
}

int BitStream::getBitIndice() {
	return this->bitIndice;	
}

int BitStream::getByteIndice() {
	return this->byteIndice;
}

int BitStream::getByteArrayLen() {
	return this->byteArrayLen;	
}

int BitStream::getBit(Bits32Sequence* seq) {
	if (byteIndice == this->byteArrayLen) {
		return 0;/*nenhum bit lido, fim do BitStream*/;
	}
	seq->clrSequence();
	Bits32Sequence* ret = new  Bits32Sequence(
					(unsigned int)byteArray[byteIndice]);
	ret->deslocRight(7 - bitIndice);
	ret->binaryAnd(0x1);
	bitIndice++;
	if (bitIndice == 8) {
		bitIndice = 0;
		byteIndice++;
	}
	seq->binaryOr(ret);
	delete ret;
	return 1; /* 1 bit lido */
}

int BitStream::getNbits(Bits32Sequence* seq, int n) {
	if (!(n > 0) || !(n <= 17)) {
		BadArgumentException excep ((char*) "BitStream::getNbits()");
		throw excep;	
	}
	Bits32Sequence aux; /*não sei porque mais só funciona assim, declarado estatícamente*/
	seq->clrSequence();
	for (int i = 0; i < n; i++) {
		if(getBit(&aux)) {
			seq->binaryOr(&aux);
			seq->deslocLeft(1);
		} else { /*não conseguiu retornar o bit*/
			seq->deslocRight(1);
			return i;
		}
		
	}
	seq->deslocRight(1);
	return n;
}

}
}
